#include <Precomp.h>
#include "defs.h"
#include "Application.h"
#include "ServerConnection.h"
#include "ClientListener.h"
#include "BaseGameState.h"
#include "GameStateLogin.h"
#include "packet.h"
#include "GameWorld.h"
#include "UIManager.h"
#include "AVUIButton.h"
#include "AVUITextBox.h"
#include "AVUINavigationWindow.h"
#include "AVUITransitioningPage.h"

using namespace AVUI;
extern "C"
{
DWORD __stdcall timeGetTime(VOID); 
};

/* Ok. We need to play games with states here -- If we specify a username and password, it'll just create an account. We need to verify one exists. 
   State tables, here we come. */

void CGameStateLogin::Initialize(CNetrekClientListener* pListener)
{
    CBaseGameState::Initialize(pListener);

    FrameworkElement* pFE = CUIManager::LoadXamlScene(L"Media\\Xaml\\Login.xaml");
    m_pRoot = pFE;

    ((NavigationWindow*)Application::get_Current()->get_MainWindow())->Navigate(m_pRoot);

    if(m_pRoot != NULL)
    {
        RoutedEventArgs eventArgs(TransitioningPage::get_TransitionInEvent());
        m_pRoot->RaiseEvent(&eventArgs);
    }

    pFE->Release();
    pFE = NULL;


    CUIManager::FindButton(m_pRoot, L"ButtonCancel")->add_Click(RoutedEventHandler::Create(this, &CGameStateLogin::CancelButtonClicked));
    CUIManager::FindButton(m_pRoot, L"ButtonLogin")->add_Click(RoutedEventHandler::Create(this, &CGameStateLogin::LoginButtonClicked));
    CUIManager::FindButton(m_pRoot, L"ButtonCreateNew")->add_Click(RoutedEventHandler::Create(this, &CGameStateLogin::CreateNewButtonClicked));

    if(pListener->GetCurrentState() == eNetrekClientState_GetServerName)
    {
        m_eLoginState = eLoginState_PendingInit;

        pListener->GetUIManager()->ShowCancelDialog(L"Retrieving server state", DialogResultCallback(&CGameStateLogin::InitDialogCancel, this));
    }
    else
    {
        m_eLoginState = eLoginState_Idle;
    }

    m_initReceived = false;
    m_dwTimeBegan = timeGetTime();
}

void CGameStateLogin::FrameStart()
{
    m_pListener->GetServerConnection()->UpdateWithPacketSink(this);

    if(m_initReceived && m_eLoginState == eLoginState_PendingInit && (timeGetTime() - m_dwTimeBegan) > 3000)
    {
        m_pListener->GetUIManager()->EndCurrentDialog(eDialogResult_OK);
        m_eLoginState = eLoginState_Idle;
    }
}

void CGameStateLogin::Cleanup()
{
    Application::get_Current()->get_MainWindow()->set_Content(NULL);
}

bool CGameStateLogin::ProcessPacket(EServerPacketType ePacketType, const packet_base* pPacket)
{
    if(ePacketType == EServerPacketType_You && m_eLoginState == eLoginState_PendingInit)
    {
        m_initReceived = true;
    }

    if(ePacketType == EServerPacketType_Login)
    {
        const login_spacket* pLoginPacket = (const login_spacket*) pPacket;

        if(pLoginPacket->accept)
        {
            if(m_eLoginState == eLoginState_Verifying)
            {
                m_pListener->GetServerConnection()->SendLoginRequest(m_szLoginName, m_szLoginPass, "", false);
                m_eLoginState = eLoginState_LoggingIn;
            }
            else if(m_eLoginState == eLoginState_LoggingIn)
            {
                TransitionMoveToNewState(m_pRoot, eNetrekClientState_TeamAndShipSelect);
            }
        }
        else
        {
            m_pListener->GetUIManager()->ShowOKDialog(L"Invalid login.", DialogResultCallback(&CGameStateLogin::ErrorDialogOK, this));
            m_eLoginState = eLoginState_Idle;
        }

        return false;
    }

    m_pListener->GetGameWorld()->ProcessPacket(ePacketType, pPacket);

    return true;
}

void CGameStateLogin::InitDialogCancel(EDialogResult eDialogResult)
{
    if(eDialogResult == eDialogResult_Cancel)
    {
        CBaseGameState::TransitionMoveToNewState(m_pRoot, eNetrekClientState_GetServerName);
    }
}

static bool IsWhitespace(const char* szText)
{
    int iLen = strlen(szText);

    for(int i = 0; i < iLen; i++)
    {
        if(!isspace(szText[i]))
        {
            return false;
        }
    }
    return true;
}

void CGameStateLogin::LoginButtonClicked(AVUI::Object*, AVUI::RoutedEventArgs*)
{
    if(m_eLoginState != eLoginState_Idle)
    {
        return;
    }

    String* pStringUsername = CUIManager::FindTextBox(m_pRoot, L"Username")->get_Text();
    String* pStringPass = CUIManager::FindTextBox(m_pRoot, L"Password")->get_Text();

    if(pStringUsername != NULL)
    {
        pStringUsername->ConvertToAnsi(m_szLoginName, sizeof(m_szLoginName));
    }
    else
    {
        m_szLoginName[0] = '\0';
    }

    if(pStringPass != NULL)
    {
        pStringPass->ConvertToAnsi(m_szLoginPass, sizeof(m_szLoginPass));
    }
    else
    {
        m_szLoginPass[0] = '\0';
    }

    if(IsWhitespace(m_szLoginName))
    {
        m_pListener->GetUIManager()->ShowOKDialog(L"Invalid login name.", DialogResultCallback(&CGameStateLogin::ErrorDialogOK, this));
        return;
    }

    m_eLoginState = eLoginState_Verifying;
    m_pListener->GetServerConnection()->SendLoginRequest(m_szLoginName, m_szLoginPass, "", true);
}

void CGameStateLogin::CancelButtonClicked(AVUI::Object*, AVUI::RoutedEventArgs*)
{
    CBaseGameState::TransitionMoveToNewState(m_pRoot, eNetrekClientState_GetServerName);
}

void CGameStateLogin::CreateNewButtonClicked(AVUI::Object*, AVUI::RoutedEventArgs*)
{
    if(m_eLoginState != eLoginState_Idle)
    {
        return;
    }

    CBaseGameState::TransitionMoveToNewState(m_pRoot, eNetrekClientState_CreateNewLogin);
}


